package cn.turboinfo.fuyang.api.domain.mini.usecase.order;

import cn.turboinfo.fuyang.api.domain.common.service.address.AddressService;
import cn.turboinfo.fuyang.api.domain.common.service.order.ServiceOrderService;
import cn.turboinfo.fuyang.api.domain.common.service.product.ProductService;
import cn.turboinfo.fuyang.api.domain.common.service.product.ProductSkuService;
import cn.turboinfo.fuyang.api.domain.common.usecase.AbstractUseCase;
import cn.turboinfo.fuyang.api.entity.common.enumeration.order.ServiceOrderCreditRatingStatus;
import cn.turboinfo.fuyang.api.entity.common.enumeration.order.ServiceOrderPayStatus;
import cn.turboinfo.fuyang.api.entity.common.enumeration.order.ServiceOrderRefundStatus;
import cn.turboinfo.fuyang.api.entity.common.enumeration.order.ServiceOrderStatus;
import cn.turboinfo.fuyang.api.entity.common.enumeration.profit.ProfitSharingStatus;
import cn.turboinfo.fuyang.api.entity.common.pojo.address.Address;
import cn.turboinfo.fuyang.api.entity.common.pojo.order.ServiceOrder;
import cn.turboinfo.fuyang.api.entity.common.pojo.order.ServiceOrderCreator;
import cn.turboinfo.fuyang.api.entity.common.pojo.product.Product;
import cn.turboinfo.fuyang.api.entity.common.pojo.product.ProductSku;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Objects;

/**
 * 服务下单
 *
 * @author sunshow
 */
@Slf4j
@RequiredArgsConstructor
@Component
public class MiniConsumerPlaceServiceOrderUseCase extends AbstractUseCase<MiniConsumerPlaceServiceOrderUseCase.InputData, MiniConsumerPlaceServiceOrderUseCase.OutputData> {

    private final ServiceOrderService serviceOrderService;

    private final ProductSkuService productSkuService;

    private final ProductService productService;

    private final AddressService addressService;

    @Override
    protected OutputData doAction(InputData inputData) {
        Long productSkuId = inputData.getProductSkuId();
        Long staffId = inputData.getStaffId();
        Long userId = inputData.getUserId();
        String comment = inputData.getComment();
        LocalDateTime scheduledStartTime = inputData.getScheduledStartTime();
        Long addressId = inputData.getAddressId();

        Address address = addressService.getByIdEnsure(addressId);
        if (!Objects.equals(address.getUserId(), userId)) {
            throw new IllegalArgumentException("地址不属于该用户");
        }

        ProductSku productSku = productSkuService.getByIdEnsure(productSkuId);
        Long productId = productSku.getProductId();
        Product product = productService.getByIdEnsure(productId);

        ServiceOrderCreator creator = ServiceOrderCreator.builder()
                .withUserId(userId)
                .withCategoryId(product.getCategoryId())
                .withProductSkuId(productSkuId)
                .withProductId(productId)
                .withCompanyId(product.getCompanyId())
                .withShopId(product.getShopId())
                .withStaffId(staffId)
                .withSpecList(productSku.getSpecList())
                .withComment(comment != null ? comment : "")
                .withScheduledStartTime(scheduledStartTime)
                .withScheduledEndTime(scheduledStartTime.plusHours(2))
                .withOrderStatus(ServiceOrderStatus.INIT)
                .withPrice(productSku.getPrice())
                .withPayStatus(ServiceOrderPayStatus.UNPAID)
                .withRefundStatus(ServiceOrderRefundStatus.INIT)
                .withAddressId(addressId)
                .withLongitude(address.getLongitude())
                .withLatitude(address.getLatitude())
                .withContact(address.getContact())
                .withGenderType(address.getGenderType())
                .withMobile(address.getMobile())
                .withDivisionId(address.getDivisionId())
                .withPoiName(address.getPoiName())
                .withDetail(address.getDetail())
                .withAdditionalFee(BigDecimal.ZERO)
                .withDiscountFee(BigDecimal.ZERO)
                .withPrepaid(BigDecimal.ZERO)
                .withCreditRatingStatus(ServiceOrderCreditRatingStatus.INIT)
                .withProfitSharingStatus(ProfitSharingStatus.INIT)
                .build();

        ServiceOrder serviceOrder = serviceOrderService.save(creator);

        return OutputData.builder()
                .serviceOrderId(serviceOrder.getId())
                .build();
    }

    @EqualsAndHashCode(callSuper = true)
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Builder
    public static class InputData extends AbstractUseCase.InputData {

        /**
         * 下单用户ID
         */
        @NotNull(message = "用户ID不能为空")
        private Long userId;

        /**
         * 产品SKU
         */
        @NotNull(message = "产品SKU不能为空")
        private Long productSkuId;

        /**
         * 服务人员ID
         */
        // TODO 可以先不支持指定服务人员下单
        private Long staffId;

        /**
         * 下单备注信息
         */
        private String comment;

        /**
         * 服务开始时间
         */
        // TODO 先只支持预约上门时间
        @NotNull(message = "服务预约开始时间不能为空")
        private LocalDateTime scheduledStartTime;

        /**
         * 选择的地址ID
         */
        // TODO 先只支持已保存地址选择提交
        @NotNull(message = "服务地址不能为空")
        private Long addressId;

    }

    @Getter
    @Setter
    @Builder
    public static class OutputData extends AbstractUseCase.OutputData {

        /**
         * 下单完成结果信息
         */
        private Long serviceOrderId;

    }
}
